#include "strutil.h"
#include <sstream>

namespace strutil {
    vector<string> split(const string& str, const string& token) {
	    vector<string> strvec;
	    string::size_type pos1, pos2;
	    pos2 = str.find(token);
	    pos1 = 0;
	    while (string::npos != pos2) {
		    strvec.push_back(str.substr(pos1, pos2 - pos1));
		    pos1 = pos2 + 1;
		    pos2 = str.find(token, pos1);
	    }
	    strvec.push_back(str.substr(pos1));
	    return strvec;
    }

    string getParentPath(const string& path) {
	    if (path.size() == 0) {
		    return path;
	    }

	    string::size_type pos = path.find("/");
	    if (pos == string::npos) {
		    return "";
	    } else {
		    return path.substr(0, pos);
	    }
    }

    bool startsWith(const string& s, const string& prefix) {
	    return s.find(prefix) == 0;
    }

    bool endsWith(const string& s, const string& suffix) {
	    size_t i = s.rfind(suffix);
	    return (i != string::npos) && (i == (s.length() - suffix.length()));
    }

    wstring string2wstring(const string& s) {
	    wstring temp(s.length(), L' ');
	    copy(s.begin(), s.end(), temp.begin());
	    return temp;
    }

    size_t trim(char *s) {
	    char *p = s;
	    size_t l = strlen(p);

	    if (l > 0) {
		    while (isspace(p[l - 1]))
			    p[--l] = 0;
		    while (*p && isspace(*p))
			    ++p, --l;

		    memmove(s, p, l + 1);
	    }

	    return l;
    }

    void trim(std::string& str, const std::string & chrsToTrim) {
	    size_t startIndex = str.find_first_not_of(chrsToTrim);
	    if (startIndex == std::string::npos) {
		    str.erase();
		    return;
	    }
	    str = str.substr(startIndex, str.size() - startIndex);
	    str = str.substr(0, str.find_last_not_of(chrsToTrim) + 1);
    }

    void toLowerCase(string& str) {
	    for (size_t i = 0; i < str.length(); ++i) {
		    if (str[i] >= 'A' && str[i] <= 'Z') {
			    str[i] += ('a' - 'A');
		    }
	    }
    }

    string getLowerCase(const string& s) {
	    string str = s;
	    toLowerCase(str);
	    return str;
    }

    string joint(const vector<string>& vecStr, const string& str) {
	    if (vecStr.size() == 0) {
		    return "";
	    }
	    stringstream ss;
	    ss << vecStr[0];

	    for (size_t i = 1; i < vecStr.size(); ++i) {
		    ss << str << vecStr[i];
	    }
	    return ss.str();
    }

    void encodeBuf(char **buf, int size) {
	    // decode buffer
	    int lengthOfKey = 19;
	    unsigned char encryptChars[] = {0x1c, 0xa3, 0x4b, 0x12, 0x77, 0x84, 0xaa,
			    0x3b, 0x2b, 0xb2, 0x23, 0x7c, 0xee, 0xef, 0xf2, 0xa0,
			    0x3b, 0x2b, 0xcc};
	    int index = 0;
	    int count = 0;
	    while (count < size) {
		    (*buf)[count++] ^= encryptChars[index++];
		    if (index == lengthOfKey) {
			    index = 8;
		    }
	    }


	    //
    }

    void replace(string& s, const string& oldStr, const string& newStr) {
	    auto pos = s.find(oldStr, 0);
	    while(pos != string::npos) {
		    s.replace(pos, oldStr.size(), newStr);
		    pos = s.find(oldStr, 0);
	    }
    }
}

